#include <stdio.h>
#include "api.h"
#include "sdl.h"
#include "ctype.h"
#define DII_ID					0x1002
#define DDB_ID					0x1003   
#define PROTOCOL_DISCRIMINATOR  0x11
#define DSMCC_TYPE              0x03
#define MAX_MESSAGE_SIZE		0xFFFF
#define MESSAGE_LENGTH_INDEX	0x0A
#define MESSAGE_DMID_INDEX		(MESSAGE_LENGTH_INDEX + 2)
#define MESSAGE_DBID_INDEX		(MESSAGE_DMID_INDEX + 4)
#define MESSAGE_HEAD_LENGTH     (MESSAGE_DBID_INDEX + 2)
#define FALSE 0

//#include "android/log.h"

#define LOG_TAG "LOADER"
#define LOGI(...) //__android_log_print(ANDROID_LOG_INFO  , LOG_TAG, __VA_ARGS__)



typedef struct _moduleInfo_t{
	unsigned char moduleId;
	unsigned char blockNumber;
	unsigned long startAddr;
	unsigned short size;
	struct _moduleInfo_t   *next;
}moduleInfo_t;

typedef struct  {
	unsigned long diiAddr;
	unsigned short diiSize;
	moduleInfo_t *pmoduleInfo;
}DLDII_t;


static FILE* s_pfsdl = NULL;
static DLDII_t *s_pDLDII = NULL;


int OpenSdlFile(char *filename)
{
	SM_Printf("OpenSdlFile() - entry!\r\n");
	if (s_pfsdl)
	{
		fclose(s_pfsdl);
		s_pfsdl = NULL;
	}
	if (strlen(filename) == 0)
	{
		SM_Printf_Error("OpenSdlFile() - info, Filename is NULL\r\n");
	//	DisplayMessageOnDlg("[Mixterm] Please input the SDL file path\n");	
	}
	else
	{//"/data/data/com.smit.livevideo/files/icast.sdl"
		if ((s_pfsdl = fopen(filename, "rb")) == NULL)
		{
			SM_Printf_Error("OpenSdlFile() - error, fopen error\r\n");
			return -1;
		}
	}
	SM_Printf("OpenSdlFile() - info, fopen SDL OK\r\n");
	return 0;
}

int CloseSdlFile()
{
	if (s_pfsdl)
	{
		fclose(s_pfsdl);
		s_pfsdl = NULL;
	}
	return 0;
}

static int FileGetOneMessageInfo(unsigned long *startAddr, unsigned short *size, 	unsigned char *moduleId, unsigned char *blockNumber)
{
	unsigned short messageId;
	unsigned short messageLength;
	unsigned char message[MESSAGE_HEAD_LENGTH];
	int ret = 0;
	int i ;
	char temp[10] = {""};
	char buf[256]= {""};

	if (!s_pfsdl)
		return -1;

	*startAddr = ftell(s_pfsdl);
	if(fread(message, 1, MESSAGE_HEAD_LENGTH, s_pfsdl) != MESSAGE_HEAD_LENGTH)
		ret = -1;
	
	for(i=0; i<MESSAGE_HEAD_LENGTH; i++ )
	{
			sprintf(temp, "%02x ",message[i] );
			strcat(buf, temp);
	}
	if (message[0] != PROTOCOL_DISCRIMINATOR || message[1]!= DSMCC_TYPE)
		ret = -2;
	else
	{
		messageId =  ASN_READ_UINT16(&message[2]);
		messageLength = ASN_READ_UINT16(&message[MESSAGE_LENGTH_INDEX]);
		
		if (messageId == DDB_ID)
		{
			*moduleId = message[MESSAGE_DMID_INDEX + 1];
			*blockNumber = message[MESSAGE_DBID_INDEX + 1];
		}
		else
		{
			*moduleId = 0xFF;
			*blockNumber = 0xFF;
		}

		*size = MESSAGE_DMID_INDEX + messageLength;
		fseek(s_pfsdl, *startAddr + *size, SEEK_SET);
	}
	return ret;
}

int FileStructInit(void)
{
	unsigned long startAddr;
	unsigned short size;
	unsigned char moduleId;
	unsigned char blockNumber;
	moduleInfo_t *pmoduleInfo;
	int ret = 0;
	
	if (!s_pfsdl)
		return -1;

	fseek(s_pfsdl, 0, SEEK_SET);
	ret = FileGetOneMessageInfo(&startAddr, &size, &moduleId, &blockNumber);
	if (ret != 0)
		ret = -1;
	else
	{
		//s_pDLDII = new DLDII_t;
		s_pDLDII = malloc(sizeof(DLDII_t));
		if (s_pDLDII == NULL)
			ret = -2;
		else
		{	
			s_pDLDII->diiAddr = startAddr;
			s_pDLDII->diiSize = size;
			s_pDLDII->pmoduleInfo = NULL;

			while (1)
			{
				ret = FileGetOneMessageInfo(&startAddr, &size, &moduleId, &blockNumber);
				if (ret != 0)
					break;

			
				if (s_pDLDII->pmoduleInfo == NULL)
				{
					s_pDLDII->pmoduleInfo = malloc(sizeof(moduleInfo_t));
					pmoduleInfo = s_pDLDII->pmoduleInfo;
				}
				else
				{
					pmoduleInfo->next = malloc(sizeof(moduleInfo_t));
					pmoduleInfo = pmoduleInfo->next;
				}

				pmoduleInfo->moduleId = moduleId;
				pmoduleInfo->blockNumber = blockNumber;
				pmoduleInfo->startAddr = startAddr;
				pmoduleInfo->size = size;
				pmoduleInfo->next = NULL;
			//	SM_Printf("moduleId = %d",moduleId);
			//	SM_Printf("blockNumber = %d",blockNumber);
			//	SM_Printf("size = %d",size);
			}
		}
	}
	return 0;
}

void DelDLDII(void)
{
	moduleInfo_t *pmoduleInfo, *temppmoduleInfo;
	
	if (!s_pDLDII)
		return;

	pmoduleInfo = s_pDLDII->pmoduleInfo;
	//free(s_pDLDII->pmoduleInfo);
	if(s_pDLDII)
		free(s_pDLDII);

	while (pmoduleInfo)
	{
		temppmoduleInfo = pmoduleInfo;
		pmoduleInfo = pmoduleInfo->next;
		//delete(temppmoduleInfo);
	}
}

int GetDiiDataInfo(unsigned long *dwStartAddr, unsigned short *dwSize)
{
	if (!s_pDLDII)
		return -1;

	*dwStartAddr = s_pDLDII->diiAddr;
	*dwSize = s_pDLDII->diiSize;
	return 0;
}

int GetDdbDataInfo(unsigned short wModuleId, unsigned short mBlockNumber, unsigned long *dwStartAddr, unsigned short *dwSize)
{
	moduleInfo_t *pmoduleInfo;

	if (!s_pDLDII)
		return -1;

	pmoduleInfo = s_pDLDII->pmoduleInfo;
	while (pmoduleInfo != NULL)
	{
		if (pmoduleInfo->moduleId == wModuleId && pmoduleInfo->blockNumber == mBlockNumber)
		{
			*dwStartAddr = pmoduleInfo->startAddr;
			*dwSize = pmoduleInfo->size;
			SM_Printf("GetDdbDataInfo() - info, moduleId = %d",wModuleId);
			SM_Printf("GetDdbDataInfo() - info, blockNumber = %d",mBlockNumber);
			SM_Printf("GetDdbDataInfo() - info, size = %d",*dwSize);
			return 0;
		}
		pmoduleInfo = pmoduleInfo->next;
	}
	return -1;
}

unsigned int FileDataRead(char* pBuf, unsigned long offset, unsigned long length)
{
	DWORD dwErrCode;
	UINT  acctualReadLen = 0;

	if (!s_pfsdl)
		return 0;
	
	if ((dwErrCode = fseek(s_pfsdl, offset, SEEK_SET)) != 0)
	{
		SM_Printf_Error("FileDataRead() - error, FileDataRead fseek error\r\n");
		//dwErrCode = GetLastError();
		//DisplayMessageOnDlg("[Mixterm] Fseek failed Error(%x).\n", dwErrCode);	
	}
	else
	{
		acctualReadLen = fread(pBuf, sizeof(char), length, s_pfsdl);
		if (acctualReadLen < length)
			acctualReadLen = 0;	
	}
	return acctualReadLen;
}

unsigned long GetFileLength()
{
	unsigned long fileLength;

	if (!s_pfsdl)
		return 0;

	fseek(s_pfsdl,0,SEEK_END);
	fileLength = ftell(s_pfsdl);

	return fileLength;
}
